'''# Third_party'''
from selenium.webdriver.support.ui import Select
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
# from kdtest import GSTORE, reset_implicitlyWait
from reference import GSTORE, INFO
from utils.decorator import reset_implicitlyWait

'''# built_in'''
import re
import os
import traceback

'''# custom'''
# .utils
from .utils.tool import isToolClass



class OA_webUI(object):

    def __repr__(self) -> str:
        return '公共UI操作方法库'


    def __init__(self) -> None:
        self.__CDCG = {}  # 全局数据缓存
        self.__logicFunction_Object = isToolClass()
        self.__elementNode_Data = self.__logicFunction_Object.raw_YamlTxt(f'{os.path.dirname(__file__)}\\elementData\\elementData.yaml')  # 读取WebUI公共套件的节点数据
        self.__ModularNode_Information = self.__logicFunction_Object.raw_YamlTxt(f'{os.path.dirname(__file__)}\\elementData\\modularInformation.json')  # 读取goto_Modular方法的各级模块节点信息
    

    '''# 用户登录'''
    def userLogin(self, userName=None, userPassword=None):
        '''
         参数：
            @param userName : 用户名
            @param userPassword : 密码
        '''
        KEYWORD = GSTORE['keyWord']  # 取出关键字对象

        if userName != None:
            KEYWORD.input_text(*self.__elementNode_Data['login']['userName'], content=userName)  # 用户名

        if userPassword != None:
            KEYWORD.input_text(*self.__elementNode_Data['login']['password'], content=userPassword)  # 密码

        # 点击登录按钮
        KEYWORD.click_btn(*self.__elementNode_Data['login']['submit'])


    '''# frame跳转封装'''
    def jumpFrame(self, Hierarchy):
        '''
        参数：
            @param Hierarchy : 代表要跳转的frame的层级以及，对应层级的节点 | List类型; Hierarchy = [3,['id', 'index', 'src']]
        
        注意：
            1、函数不做正确性判断，注意传入的层级节点的对应关系正确
            2、函数中的可以处理三种类型的“iframe标识”分别为 [标签ID、标签索引、标签src属性值]
        '''
        driver = GSTORE['driver']; KEYWORD = GSTORE['keyWord']

        driver.switch_to.default_content()  # 焦点切换回原页面
        operFrameList = Hierarchy[1]; operFrameIden = None
        for Item in operFrameList:
            try:
                operFrameIden = int(Item)  # 索引
            except Exception as error:
                if re.findall(r"[http\[s\]?://]?([/]|[\\])+", Item):
                    frame_Ele = KEYWORD.locators('tag_names', 'iframe')
                    for index in range(0, len(frame_Ele)):
                        if Item in frame_Ele[index].get_attribute('src'):
                            operFrameIden = index; break  # 路径索引
                else:
                    operFrameIden = Item  # ID

            '''iframe焦点跳转'''
            driver.switch_to.frame(operFrameIden)


    '''# 错误处理封装 【强制提示】'''
    @reset_implicitlyWait(2)
    def errorHandle(self, type=False, prompt_input=None):
        '''
         alert / 系统提示信息 / 右上角消息弹框
         参数：
            @param type : True代表点击alert弹框的【确定】按钮，False代表点击alert弹框的【取消】按钮
            @param alert_input : 代表在prompt弹框时要输入的文本内容

        注：
            1、提示处理优先级为 alert > 系统提示信息 > 右上角消息弹框
            2、由于系统中“tips 系统提示框”的操作按钮并不统一，故函数中采用“对照列表 [TIPS_BTN_ELE]”的方法进行操作
            3、函数中的元素判断采用EC[预期条件]模块方式
        '''
        driver = GSTORE['driver']; KEYWORD = GSTORE['keyWord']  # 暂存对象取出
        
        OPERATION = ['ALERT_ELE', 'TIPS_ELE', 'TIPS_SPRING_ELE']
        RETURN_Information = None; ALERT_ELE = None; TIPS_ELE = None; TIPS_SPRING_ELE = None # 过渡操作变量定义
        TIPS_BTN_ELE = self.__elementNode_Data['error']['TIPS_BTN_ELE']  # “系统提示信息处理” 操作按钮[返回、关闭..]元素节点暂存

        try:
            ALERT_ELE = WebDriverWait(driver, 2, 0.5).until(EC.alert_is_present())  # alert 提示框判断
        except Exception as error:
            TIPS_ELE = EC.presence_of_element_located((By.CSS_SELECTOR, self.__elementNode_Data['error']['TIPS']))(driver) # 系统提示信息 元素判断
            if not TIPS_ELE:
                TIPS_SPRING_ELE = EC.presence_of_all_elements_located((By.CSS_SELECTOR, self.__elementNode_Data['error']['BOUNCED']))(driver)  # 系统右上角提示弹框

        '''INFO(f'ALERT_ELE is {ALERT_ELE}  TIPS_ELE is {TIPS_ELE}  TIPS_SPRING_ELE is {TIPS_SPRING_ELE}')'''
        for key in OPERATION:
            if eval(key):
                if key == 'ALERT_ELE':
                    '''alert提示框操作'''
                    RETURN_Information = ALERT_ELE.text
                    if prompt_input: ALERT_ELE.send_keys(prompt_input)  # prompt弹框输入判断
                    ALERT_ELE.accept() if type else ALERT_ELE.dismiss()  # 模拟alert点击
                    break
                elif key == 'TIPS_ELE':
                    '''系统提示信息处理'''
                    RETURN_Information = TIPS_ELE.text

                    for key in TIPS_BTN_ELE.keys():
                        BTN_ELE = KEYWORD.locators(*TIPS_BTN_ELE[key])  # 操作按钮查找
                        if BTN_ELE:
                            KEYWORD.click_btn(*TIPS_BTN_ELE[key]); break  # 操作按钮点击
                    break
                else:
                    '''右上角消息弹框处理'''
                    self.TipsSpringFrame('readAll')  # 调用公共库
                    break
            else:
                '''元素未加载；不做操作'''
                pass
        
        INFO(f'提示信息：{RETURN_Information}')
        if RETURN_Information: return RETURN_Information


    '''# 文本弱提示处理【弱提示】'''
    def WeakHint(self):
        '''用于处理文本输入框的弱提示'''
        driver = GSTORE['driver']  # 取出driver对象
        this_Weak_Text = None

        try:
            WeakElement = WebDriverWait(driver, 2, 1).until(
                EC.visibility_of_element_located((By.XPATH, self.__elementNode_Data['WeakHint']['Weak']))
            )
        except Exception as error:
            INFO('无弱提示！')
        else:
            if WeakElement.is_displayed():  # 提示框当前显示状态判断
                this_Weak_Text = "".join(re.findall(r'[0-9\u4e00-\u9fa5]', WeakElement.text))
        
        INFO(f'提示文本：{this_Weak_Text}')
        return this_Weak_Text


    '''# 人员选择逻辑封装'''
    def personnelChoice(self, type, dataList='', name='', department=''):
        '''
         参数：
            @param type : 以何种方式添加【'0'部门、'1'角色、'2'分组、'3'在线、'4'检索】
            @param dataList : 要进行选择操作对应的参数
             按照部门选择输入参数为：dataList=[部门名称，人员姓名] | 用来存放按照部门进行添加时的人员和部门信息
             按照角色选择输入参数为： dataList=[人员角色名称，人员姓名]  | 用来存放按照角色进行添加时的人员和角色信息
             按照分组选择输入参数为：dataList=[分组名称，人员姓名]  | 用来存放按照分组进行添加时的人员和分组信息
            @param name : 选填 | 类型为字符串，用来存放按照检索进行添加时的人员姓名，如果有两个同名人员默认取第一个
            @param department : 选填 | 类型为字符串，代表部门名称；当需要将整个部门的人员全部添加时给其传参即可

        注意：
            1、按照部门选择时，单纯的一级目录结构参数格式为：dataList = [部门名称，人员姓名]
            2、大于一级的目录结构参数格式为：dataList = [num(目录层级2,3,4)，[父级目录名称，子级目录名称n...]，人员姓名]
             例如: dataList=[4,['市场营销部', '销售部', '北京销售部', '销售三组'],'温炳康']
            3、department使用时需要将type的值填充为'0'【部门方式添加】，才可以使用
        '''
        KEYWORD = GSTORE['keyWord']; driver = GSTORE['driver']  # 取出关键字对象

        NAV = KEYWORD.locators(*self.__elementNode_Data['personnel']['list']); after_NAV = NAV[1:] if ('已选' in  NAV[0].get_attribute('title')) else NAV  # 顶部导航按钮舍弃“已选”
        if type != '4': after_NAV[int(type)].click()  # 导航按钮点击

        '''人员列表操作'''
        if type in ['3','4']:
            '''在线、检索方式添加'''
            if type == '4': KEYWORD.input_text(*self.__elementNode_Data['personnel']['search'], content=name)
            KEYWORD.click_btn(*self.__elementNode_Data['personnel']['online' if type == '3' else 'result'])  # 人员选择

        else:
            '''其它方式'''
            if not department:  # 判断是否要部门全部选择
                TARGETING = self.__elementNode_Data['personnel']['TARGETING']
                DEPT_MENU = self.__elementNode_Data['personnel']['DEPT_MENU'][type]
                DEPT_ITEM = self.__elementNode_Data['personnel']['DEPT_ITEM'][type]
                if (len(dataList) > 2):
                    '''多级部门;添加'''
                    for i in range(0, dataList[0]):
                        KEYWORD.click_btn(TARGETING, DEPT_MENU.replace('INSERT', dataList[1][i]))

                    KEYWORD.click_btn(TARGETING, DEPT_ITEM.replace('INSERT', dataList[-1]))  # 点击目标人员
                else:
                    '''一级部门，角色，分组;添加'''
                    KEYWORD.click_btn(TARGETING, DEPT_MENU.replace('INSERT', dataList[0]))  # 部门
                    KEYWORD.click_btn(TARGETING, DEPT_ITEM.replace('INSERT', dataList[1]))  # 点击目标人员
            else:
                # 部门全部人员添加
                CHECKBOX = self.__elementNode_Data['personnel']['CHECKBOX']; KEYWORD.click_btn('xpath', CHECKBOX.replace('INSERT', department))  # 部门复选框点击
                try:
                    WebDriverWait(driver, 1, 0.5).until(
                        EC.presence_of_element_located((By.XPATH, self.__elementNode_Data['personnel']['MASK'].replace('INSERT', department)))
                    )
                except Exception as error:
                    pass
            
        '''组件信息提交'''
        try:
            KEYWORD.click_btn(*self.__elementNode_Data['personnel']['confirm'])  # 确定按钮
        except Exception as error:
            pass


    '''# 日期选择'''
    def setDate(self, expectDate):
        '''根据传入的日期形参，进行日期选择'''
        ''' 
         参数：
            @param expectDate: 要进行选择的日期；注意这里日期格式应为YYYY-MM-DD；如： 2021-9-24
        '''
        KEYWORD = GSTORE['keyWord']  # 取出公共暂存对象
        self.jumpFrame([1,[self.__elementNode_Data['setDate']['frameSrc']]])  # 根据src属性，将焦点跳入日期选择对话框

        '''## 年、月、日操作步骤封装'''
        def dataOperation(actualDate, int_expectDate):
            '''
            # actualDate ：函数主逻辑中获取到的当前系统日期
            # int_expectDate ：函数主逻辑中处理成int数组的预期操作日期
            '''
            INFO(f'操作选择日期：{expectDate}, 对话框当前日期：{actualDate}')
            expectValue = list(map(str,int_expectDate)); actualValue = actualDate.split('-')  # string 数组转换

            '''# 目标年、月选择'''
            for i in range(0, len(actualValue[:-1])):
                arrow_Type = {'Left': self.__elementNode_Data['setDate']['YLeft'], 'Right': self.__elementNode_Data['setDate']['YRight']}\
                    if len(str(actualValue[i])) == 4 else\
                        {'Left': self.__elementNode_Data['setDate']['MLeft'], 'Right': self.__elementNode_Data['setDate']['MRight']}  # 年份，月份操作按钮处理 (单、双箭头)

                if not(actualValue[i] == expectValue[i]):
                    '''循环遍历点击'''
                    arrow_Button = arrow_Type['Left'] if int(actualValue[i]) > int(expectValue[i]) else arrow_Type['Right']  # 左、右箭头按钮处理
                            
                    for j in range(0, abs(int(expectValue[i]) - int(actualValue[i]))):
                        '''左、右侧方向箭头年份、月份'''
                        KEYWORD.click_btn(*arrow_Button)
                        '''处理年份多次点击，会激活年份选择下拉列表框的问题'''
                        if KEYWORD.locator(*self.__elementNode_Data['setDate']['Y_Select_Box']).is_displayed(): KEYWORD.click_btn(*arrow_Button)  # 重复二次点击
                else:
                    '''值相等不做操作'''
                    pass
                
            '''# 目标日期选择'''
            KEYWORD.click_btn('css_selector',f'[onclick="day_Click({expectValue[0]},{expectValue[1]},{expectValue[2]});"]')
        
        '''## 函数自身逻辑'''
        Year = int(KEYWORD.getAttribute(*self.__elementNode_Data['setDate']['Y_Select_Btn']))  # 年
        Month = int(self.__logicFunction_Object.CHI(KEYWORD.getAttribute(*self.__elementNode_Data['setDate']['M_Select_Btn'], index=0)))  # 月
        Day = int(KEYWORD.locator(*self.__elementNode_Data['setDate']['action_Day']).text)  # 日

        Edate = list(map(int,expectDate.split('-')))  # 字符串‘数值列表化’处理
        if Edate == [Year, Month, Day]:
            '''日期相等'''
            KEYWORD.click_btn(*self.__elementNode_Data['setDate']['today']) 
        else:
            '''预期日期大于或小于实际日期，进行对话框操作'''
            dataOperation(f'{Year}-{Month}-{Day}', Edate)
        
        '''# 组件关闭处理'''
        try:
            KEYWORD.click_btn(*self.__elementNode_Data['setDate']['confirm_Btn'])
        except Exception as error:
            pass


    '''# 系统左上角提示信息弹框处理'''
    def TipsSpringFrame(self, type):
        '''
         参数：
            @param type  必填项 ：代表要进行的操作 exit关闭对话框、 readAll已阅全部
        '''
        KEYWORD = GSTORE['keyWord']  # 取出关键字对象
        driver = GSTORE['driver']

        try:
            tipsBoxElements = WebDriverWait(driver, 1, 0.5).until(
                EC.presence_of_all_elements_located((By.CSS_SELECTOR, self.__elementNode_Data['TSFrame']['tispElements']))
            )
        except Exception as error:
            INFO('界面无消息提示框，不做操作')
            return 0
        else:
            '''处理弹框'''
            for tipsBox_Item in tipsBoxElements:
                KEYWORD.actionBuilder_Move(*self.__elementNode_Data['TSFrame']['tispItem'], ParentObject=tipsBox_Item)  # 鼠标悬浮，调出操作按钮组
                if type == 'exit':
                    KEYWORD.click_btn(*self.__elementNode_Data['TSFrame']['exitButton'])  # 关闭
                else:
                    try:
                        KEYWORD.click_btn(*self.__elementNode_Data['TSFrame']['markAll'], ParentObject=tipsBox_Item)  # 已阅全部
                    except Exception as error:
                        KEYWORD.click_btn(*self.__elementNode_Data['TSFrame']['ignoreAll'], ParentObject=tipsBox_Item)  # 忽略全部
                    break
            return 1


    '''# 表单信息输入逻辑操作封装'''
    def FormInput(self, Parent, operationStep):
        '''
         参数:
            @param Parent: 表单的父级节点；css单元素定位方式，用于界面元素的框定查找
            @param operationStep: dict value为列表值；用来存放要操作的整体流程 
         格式：{
            'input':[..], //  'input':[[css定位方式, '输入值'],[],[]..]  # 普通文本输入框  如果为None则表示不输入
            'pass':[], //  'pass':[[css定位方式, '输入值'],[],[]..]  # 密码文本输入框  如果为None则表示不输入
            'select':[[定位，对应操作值]..]  # 下拉列表框
            'checkbox':[..] // 'checkbox':[['css定位', '操作值']], # 复选框选择
            'radio':[..] // 'radio':[[, '操作值']], # 单选框选择
            'textarea':[..] // 'textarea':[[css定位方式, '输入值'],[],[]..], # 多行文本输入框 如果为None则表示不输入
         }

        注：
            1、整个流程按照界面元素出现的顺序进行操作，注意值输入顺序
            2、字典中的key顺序可以随意书写; 字典中各key对应的value列表中的值互不影响，但要注意顺序问题
            3、select下拉列表框使用css定位方式; 如果 [定位，对应操作值] “对应操作值”为string类型代表使用value值进行选择，如果为int类型代表使用index值进行选择
            4、如果想要清除某一个输入框或者多行文本输入框中的值，则其key对应的value值应为'clear'
        '''
        KEYWORD = GSTORE['keyWord']  # 取出关键字对象
        driver = GSTORE['driver']  # 取出driver对象

        parentNode = KEYWORD.locator('css_selector', Parent)  # 表单父级元素
        # 遍历预期形参，进行流程处理
        for StepKey in operationStep:
            # 遍历形参
            operLength = len(operationStep[StepKey])  # 单类型形参长度
            
            '''流程判断'''     
            if StepKey == 'select':
                '''# 下拉列表框操作'''
                for value in range(0, len(operationStep[StepKey])):
                    select = KEYWORD.locator('css_selector', operationStep[StepKey][value][0])  # 下拉列表框 元素获取
                    mail = Select(select); OPERATION = operationStep[StepKey][value][1]

                    if isinstance(OPERATION, int): 
                        mail.select_by_index(OPERATION)  # 按照对应index值进行选择
                    else:
                        if ''.join(re.findall(r'[\u4e00-\u9fa5]', OPERATION)) == OPERATION:
                            mail.select_by_visible_text(OPERATION)  # 按照对应text值进行选择
                        else:
                            mail.select_by_value(OPERATION)  # 按照对应value值进行选择

            else:
                '''# input输入框，textarea多行文本输入框、checkbox复选按钮、radio单选按钮'''
                ''' StepKey == 'checkbox' or StepKey == 'radio' or StepKey == 'input' or StepKey == 'textarea' or StepKey == 'pass' '''
                ASSEMBLYS = KEYWORD.offLocator(parentNode, *self.__elementNode_Data['FormInput'][StepKey])  # 表单操作元素获取

                for value in range(0, operLength if operLength <= len(ASSEMBLYS) else len(ASSEMBLYS)):
                    if operationStep[StepKey][value] != None:
                        type_boolean = isinstance(operationStep[StepKey][value], list)
                        ELEMENT = KEYWORD.offLocator(parentNode, 'css_selector', operationStep[StepKey][value][0]) if type_boolean else ASSEMBLYS[value]
                        Content = operationStep[StepKey][value][-1] if type_boolean else operationStep[StepKey][value]

                        if StepKey == 'input' or StepKey == 'textarea' or StepKey == 'pass':
                            # 输入框操作
                            ELEMENT.clear()
                            if Content != 'clear': ELEMENT.send_keys(Content) # 输入/清除内容
                        else:
                            # 单、复选按钮选择操作
                            INFO(f'单、复选按钮操作前状态：{ELEMENT.is_selected()}')
                            if ELEMENT.is_selected() != Content: driver.execute_script("arguments[0].click();", ELEMENT) # 选择操作
                    else:
                        '''为None不做操作'''
                        pass


    '''# 全局系统模块菜单跳转操作封装'''
    @reset_implicitlyWait(2)
    def goto_Modular(self, firstIden=None, secondIden=None, thirdIden=None, tagIden=None, localSwitch=False):
        '''
         参数：
            @param firstIden: OA系统一级模块标识【特殊字符标识】
            @param secondIden: OA系统二级模块标识【特殊字符标识】
            @param thirdIden: OA系统三级模块标识【特殊字符标识】
            @param tagIden: 对应模块tag标签标识【阿拉伯数字】
            @param localSwitch: 局部操作开关【布尔值】

         格式：(可以按照dict和list两种格式为函数传递形参值)
            dict(传入形参顺序与函数定义的形参位置不对应)/list(传入形参顺序与函数定义的形参位置对应)

            1、全局操作；目标模块不存在子模块和tag标签页(例如：个人事务-电子邮件)：
                {firstIden:'personalAffairs','secondIden':'E_Mail'} || ['personalAffairs','E_Mail']

            2、全局操作；目标模块不存在子模块但存在tag标签页(例如：个人事务-消息管理-微讯)：
                {firstIden:'personalAffairs','secondIden':'Message','tagIden':0} || 不支持list格式调用

            3、全局操作；目标模块存在子模块但不存在tag标签页(例如：行政办公-工作计划-工作计划类型设置)：
                {firstIden:'administrativeOffice','secondIden':'Work_Plan','thirdIden':'Work_Plan_Type'} || ['administrativeOffice','Work_Plan','Work_Plan_Type']
            
            4、全局操作：目标模块存在子模块同时也存在tag标签页(例如：行政办公-工作计划-工作计划管理-新建工作计划)：
                {firstIden:'administrativeOffice','secondIden':'Work_Plan','thirdIden':'Work_Plan_Query', 'tagIden':1} || ['administrativeOffice','Work_Plan','Work_Plan_Query',1]

            5、局部操作：目标模块不存在tag标签页(例如：个人事务-电子邮件、行政办公-工作计划-工作计划类型设置)：
                · 进行一次全局操作(全局路由跳转),将模块跳转至“个人事务-电子邮件”模块 → 用例步骤 → 用例步骤 →... → {'tagIden':True} || 不支持list格式调用
                · 进行一次全局操作(全局路由跳转),将模块跳转至“行政办公-工作计划-工作计划类型设置”模块 → 用例步骤 → 用例步骤 →... → {'tagIden':True} || 不支持list格式调用
            
            6、局部操作：目标模块存在tag标签页(例如：个人事务-消息管理-微讯 、行政办公-工作计划-工作计划管理-新建工作计划)：
                · 进行一次全局操作(全局路由跳转),将模块跳转至“个人事务-消息管理-微讯”模块 → 用例步骤 → 用例步骤 →... → {'tagIden':0,'tagIden':True} || 不支持list格式调用
                · 进行一次全局操作(全局路由跳转),将模块跳转至“行政办公-工作计划-工作计划管理-新建工作计划”模块 → 用例步骤 → 用例步骤 →... → {'tagIden':1, 'tagIden':True} || 不支持list格式调用

        注：
            1、方法适用于OA系统中的所有模块，包含所有“一级模块、二级模块、三级模块、tag页模块”；主要目的是为了简化“用例步骤文件”中的模块跳转步骤； 
            2、方法不会校验“各模块标识之间的层级关系是否有效以及其标识是否合法(是否存在)”，所以在使用时要注意检查你要操作的“模块标识”和“多级模块层级”是否正确；
            3、“全局操作”：不考虑当前正在处于活动状态的“模块”，直接将整个OA系统还原成初始状态(无任何菜单展开，无任何模块打开)，并根据传入的各级标识打开指定的目标模块；
            4、“局部操作”：不会对系统“展开菜单项”和“定位任务标签”进行清空操作，而是直接跳过一、二级模块直接以三级模块或者tag标签模块为起点进行操作； 
            5、“局部操作”不需要指定“各级模块标识”，但需要在调用方法进行“目标模块的局部操作”之前先调用方法完成一次“目标模块的全局操作”，目的则是为了获取“全局操作”所指定的各级模块标识信息；
            6、“局部操作”不支持用于模块之间的跳转，其本身目的只是为了用来刷新目标模块；
            7、在使用“局部操作”刷新目标模块时，不传入“tagIden对应模块tag标签标识(不论目标模块有无tag标签页)”则代表将该模块关闭(顶部选项卡)，并重新点击打开。

        方法可操作模块标识如下(按照模块的从属关系划分)：
            1、personalAffairs 代表一级模块“个人事务”可操作的下级模块如下：
             · E_Mail 代表二级模块“电子邮件”；无可操作的tag页模块

             · Message 代表二级模块“消息管理”；可操作tag页模块
              [0微讯，1事务提醒，2文件管理，3公共通讯群组管理，4临时通讯群组管理]

             · SMS 代表二级模块“手机短信”；可操作tag页模块
              [0发送手机短信，1短信发送管理，2接收短信查询]

             · Task_management 代表二级模块“任务管理”；无可操作的tag页模块

             · Announcement_Notice 代表二级模块“公告通知”；可操作tag页模块
              [0未读公告，1公告通知，2公告查询]
            
             · Journalism 代表二级模块“新闻”；可操作tag页模块
              [0未读新闻，1全部新闻，2新闻查询]

             · Vote 代表二级模块“投票”；可操作tag页模块
              [0已发布的投票，1已终止投票]

             · Personal_attendance  代表二级模块“个人考勤”；可操作tag页模块
              [0上下班登记，1手机考勤，2外出登记，3请假登记，4出差登记，5加班登记，6我的值班，7查岗记录，8上下班记录]

             · Schedule 代表二级模块“日程安排”；可操作tag页模块
              [0日程安排，1我的任务]

             · Work_log 代表二级模块“工作日志”；可操作tag页模块
              [0日志信息]

             · Address_book 代表二级模块“通讯簿”；无可操作的tag页模块

             · Wallet 代表二级模块“票夹子”；无可操作的tag页模块

             · Personal_filing_cabinet 代表二级模块“个人文件柜”；无可操作的tag页模块

             · Control_panel 代表二级模块“控制面板”；无可操作的tag页模块
            
            2、processCenter 代表一级模块“流程中心”可操作的下级模块如下：
            
            3、administrativeOffice 代表一级模块“行政办公”可操作的下级模块如下：

            4、knowledgeManagement  代表一级模块“知识管理”可操作的下级模块如下：

            5、supervision  代表一级模块“督查督办”可操作的下级模块如下：

            6、smartPortal  代表一级模块“智能门户”可操作的下级模块如下：

            7、applicationCenter  代表一级模块“应用中心”可操作的下级模块如下：

            8、reportCenter  代表一级模块“报表中心”可操作的下级模块如下：

            9、humanResources  代表一级模块“人力资源”可操作的下级模块如下：

            10、documentManagement  代表一级模块“公文管理”可操作的下级模块如下：

            11、fileManagement  代表一级模块“档案管理”可操作的下级模块如下：

            12、exchangeField   代表一级模块“交流园地”可操作的下级模块如下：

            13、openPlatform   代表一级模块“开发平台”可操作的下级模块如下：

            14、accessories   代表一级模块“附件程序”可操作的下级模块如下：

            15、systemManagement   代表一级模块“系统管理”可操作的下级模块如下：
        '''
        KEYWORD = GSTORE['keyWord']  # 取出关键字对象
        targetTag = None  # 目标tag标签节点
        targetIframe = None  # 目标iframe标识
        modularIframeDict = eval(self.__ModularNode_Information.replace('null', 'None'))  # 系统各级模块节点信息
        if firstIden and (not localSwitch): self.__CDCG['firstIden'] = firstIden
        if secondIden and (not localSwitch): self.__CDCG['secondIden'] = secondIden
        if thirdIden and (not localSwitch): self.__CDCG['thirdIden'] = thirdIden
        try:
            '''//初始化iframe焦点//'''
            KEYWORD.frame_default()
            if not localSwitch:
                '''//顶部任务标签展开检查//'''
                taskbarElement = KEYWORD.locators(*self.__elementNode_Data['gotoModular']['taskbar'])
                for index in range(0, len(taskbarElement)): KEYWORD.click_btn(*self.__elementNode_Data['gotoModular']['taskbar'], 0)

                '''//一、二级菜单展开检查//'''
                firstMenuElement = KEYWORD.locators(*self.__elementNode_Data['gotoModular']['firstMenu'])
                secondMenuElementNode = self.__elementNode_Data['gotoModular']['secondMenu']
                for f_index in range(0, len(firstMenuElement)):
                    elementID = KEYWORD.getAttribute(*self.__elementNode_Data['gotoModular']['firstMenu'], 'id', 0)
                    secondMenuElement = KEYWORD.locators('xpaths', secondMenuElementNode.replace('INSERT', elementID))
                    for s_index in range(0, len(secondMenuElement)):
                        secondMenuElement[s_index].click()  # 二级模块收起

                    firstMenuElement[f_index].click()  # 一级模块收起
            else:
                try:
                    firstIden = self.__CDCG['firstIden']
                    secondIden = self.__CDCG['secondIden']
                    thirdIden = self.__CDCG['thirdIden']
                except Exception as error:
                    pass  # 跳过
                if not tagIden:  # 判断有无传入“tag标签标识”
                    taskbarElement = KEYWORD.locators(*self.__elementNode_Data['gotoModular']['taskbar'])
                    for index in range(0, len(taskbarElement)): KEYWORD.click_btn(*self.__elementNode_Data['gotoModular']['taskbar'], 0)
        except Exception as error:
            INFO(traceback.format_exc())  # 跳过
        finally:
            if not localSwitch:
                '''//一级菜单展开//'''
                KEYWORD.click_btn(*modularIframeDict[firstIden]['selfLocatin'])
                '''//二级菜单点击//'''
                KEYWORD.click_btn(*modularIframeDict[firstIden]['subordinate'][secondIden]['locatingNodes'])
            try:
                if not modularIframeDict[firstIden]['subordinate'][secondIden]['submodule']:
                    '''//无子模块//'''
                    if localSwitch:
                        KEYWORD.click_btn(*modularIframeDict[firstIden]['subordinate'][secondIden]['locatingNodes'])
                    targetTag = modularIframeDict[firstIden]['subordinate'][secondIden]['tagPage']
                    targetIframe = modularIframeDict[firstIden]['subordinate'][secondIden]['iframe']
                else:
                    '''//存在子模块//'''
                    KEYWORD.click_btn(*modularIframeDict[firstIden]['subordinate'][secondIden]['submodule'][thirdIden]['locatinExpression'])
                    targetTag = modularIframeDict[firstIden]['subordinate'][secondIden]['submodule'][thirdIden]['thisTag']
                    targetIframe = modularIframeDict[firstIden]['subordinate'][secondIden]['submodule'][thirdIden]['thisIframe']
            except Exception as error:
                INFO(traceback.format_exc())  # 跳过
            finally:
                '''//判断有无tag标签页//'''
                if targetTag:
                    KEYWORD.click_btn(*targetTag[int(tagIden)])
                '''//iframe焦点切入//'''
                KEYWORD.switch_frame(targetIframe)

        
    '''OA数据库操作(暂未开发)'''
    def intervention_Mysql(self, ):
        '''
         参数：
            @param 
        '''
        return True
    

    '''三元判断操作(暂未开发)'''
    def ternary_Judgement(self, ):
        '''
        参数：
            @param 
        '''
        return True